﻿#pragma once
namespace LK
{
	namespace Reflection
	{
		struct PTypeNode:PDomainNode
		{
			PMETHODS(PTypeNode, TypeNode);
			/**
			@brief 构造一个类型节点*/
			PTypeNode(ptr<Type> id,ptr<String> const& name=ptr<String>::GetEmpty(), PDomainNode const&baseNode=Convert<PDomainNode const&,ptr<Object>>::RefFrom(ptr<Object>()), weakptr<TypeLibrary> const& library=Convert<weakptr<TypeLibrary> const&,ptr<Object>>::RefFrom(ptr<Object>()));
			/**
			@brief 获取基类节点列表
			@note 如果没有基类，则返回NULL*/
			ptr<Collection::IArray<PTypeNode>> GetBaseTypeNodes()const;
			/**
			@brief 移除派生节点*/
			void RemoveDerivedNode(PTypeNode const&node)const;
			/**
			@brief 添加指定名称的成员函数*/
			void AddFunction(ptr<String> const&name, Functional::PFunObjs const&fun)const;
			void AddFunction(ptr<String> const&name, Functional::PFunObjs const&fun, PDomainNode domain)const;
			/**
			@brief 添加基类*/
			void AddBaseType(ptr<Type> const&tp)const;
			/**
			@brief 获取类型大小的引用*/
			size_t& GetSizeRef()const;
			/**
			@brief 判断该类型是否从另一个类型派生*/
			bool IsDerivedFrom(PTypeNode)const;
			/**
			@brief 判断该类型是否可以动态转换到另一个类型t，isExplicit用来指定是否进行精确的类型匹配，默认为false*/
			bool CanConvertTo(ptr<Type> t,bool isExplicit=false)const;
			/**
			@brief 判断指定的参数类型是否可以用于动态构造该类型节点对应的类型的对象，isExplicit参数用以指定是否要求精确匹配，默认为false*/
			bool CanConstructFrom(ptr<Collection::IArray<ptr<Type>>>const&args, bool isExplicit=false)const;
			/**
			@brief 传入该类型对象并动态转换到另一类型对象，isExplicit参数用以指定是否要求精确匹配，默认为false*/
			ptr<Object> DynamicConvertTo(ptr<Type> dest, ptr<Object> const&source,bool isExplicit=false)const;
			/**
			@brief 动态从其它类型对象构造该类型对象，isExplicit参数用以指定是否要求精确匹配，默认为false*/
			ptr<Object> DynamicConstructFrom(ptr<Collection::IArray<ptr<Object>>>const&source, bool isExplicit=false)const;
			/**
			@brief 在该类型及派生类型中查找指定名称的节点*/
			ptr<LibraryNode> FindNodeByNameInClass(ptr<String> const&)const;
			/**
			@brief 添加转换到其它类型的函数，函数类型必须是To(from)
			@note 该方法会自动在目标类型的构造函数中进行相应的添加*/
			void AddOperatorFunction(const Functional::PFunObjs&fun);
			/**
			@brief 添加构造函数，函数类型必须是 T(Args)
			@note 如果构造函数参数只有一个，该方法会自动在该参数类型中添加一个转换函数*/
			void AddConstructFunction(const Functional::PFunObjs&fun);
			/**
			@brief 获取到其它类型的转换函数*/
			PFunctionNode GetOperatorFunctions()const;
			/**
			@brief 获取构造函数列表*/
			PFunctionNode GetConstructFunctions()const;
			/**
			@brief PTypeNode与index_t比较的方法*/
			static index_t CompareId(PTypeNode const& t, index_t id);
		};
		struct TypeNode:DomainNode
		{
			//通用方法
			BMETHODS(PTypeNode, TypeNode)
			/**
			@brief 构造一个类型节点
			@note 如果id为NULL将抛出异常*/
			TypeNode(ptr<Type> id, ptr<String> const& name = ptr<String>::GetEmpty(), PDomainNode const&baseNode = Convert<PDomainNode const&,ptr<Object>>::RefFrom(ptr<Object>()), weakptr<TypeLibrary> const& library = Convert<weakptr<TypeLibrary> const&,ptr<Object>>::RefFrom(ptr<Object>()));
			/**
			@brief 判断该类型是否从另一个类型派生*/
			bool IsDerivedFrom(PTypeNode)const;
			/**
			@brief 判断该类型是否可以动态转换到另一个类型t，isExplicit用来指定是否进行精确的类型匹配，默认为false*/
			bool CanConvertTo(ptr<Type> t, bool isExplicit = false)const;
			/**
			@brief 判断指定的参数类型是否可以用于动态构造该类型节点对应的类型的对象，isExplicit参数用以指定是否要求精确匹配，默认为false*/
			bool CanConstructFrom(ptr<Collection::IArray<ptr<Type>>>const&args, bool isExplicit = false)const;
			/**
			@brief 传入该类型对象并动态转换到另一类型对象，isExplicit参数用以指定是否要求精确匹配，默认为false*/
			ptr<Object> DynamicConvertTo(ptr<Type> dest, ptr<Object> const&source, bool isExplicit = false)const;
			/**
			@brief 动态从其它类型对象构造该类型对象，isExplicit参数用以指定是否要求精确匹配，默认为false*/
			ptr<Object> DynamicConstructFrom(ptr<Collection::IArray<ptr<Object>>>const&source, bool isExplicit = false)const;
			/**
			@brief 设置基库节点，重写LibraryNode::SetLibrary*/
			void SetLibrary(weakptr<TypeLibrary> const&lib);
			/**
			@brief 清理内部数据*/
			void Clear();
			/**
			@brief 移除派生节点，并移除该类型在派生节点中的方法*/
			void RemoveDerivedNode(PTypeNode const&node);
			/**
			@brief 添加基类（仅限有直接关系的基类）*/
			void AddBaseType(ptr<Type> const&type);
			/**
			@brief 移除基类（仅限有直接关系的基类）*/
			void RemoveBaseType(ptr<Type> const&type);
			/**
			@brief 添加指定名称的成员函数*/
			void AddFunction(ptr<String> const&name, Functional::PFunObjs fun);
			void AddFunction(ptr<String> const&name, Functional::PFunObjs fun,PDomainNode domain);
			/**
			@brief 在该类型及派生类型中查找指定名称的节点*/
			ptr<LibraryNode> FindNodeByNameInClass(ptr<String> const&)const;
			/**
			@brief 添加转换到其它类型的函数，函数类型必须是To(from)
			@note 该方法会自动在目标类型的构造函数中进行相应的添加*/
			void AddOperatorFunction(const Functional::PFunObjs&fun);
			/**
			@brief 添加构造函数，函数类型必须是 T(Args)
			@note 如果构造函数参数只有一个，该方法会自动在该参数类型中添加一个转换函数*/
			void AddConstructFunction(const Functional::PFunObjs&fun);
			/**
			@brief 获取到其它类型的转换函数*/
			PFunctionNode GetOperatorFunctions()const { return OperatorFunctions; }
			/**
			@brief 获取构造函数列表*/
			PFunctionNode GetConstructFunctions()const { return ConstructFunctions; }
			/**
			@brief 转换函数节点*/
			PFunctionNode OperatorFunctions;
			/**
			@brief 类型构造节点*/
			PFunctionNode ConstructFunctions;
			/**
			@brief 基类结点（多个）*/
			ptr<Collection::IArray<PTypeNode>> BaseTypeNodes;
			/**
			@brief 派生类型结点（多个）*/
			ptr<Collection::IArray<PTypeNode>> DerivedTypeNodes;
			/**
			@brief 该类型的大小*/
			size_t Size;
			/**
			@brief 与之关联的ptr<Type>类型信息*/
			ptr<Type> Id;
		};
	}
}
